package com.mk.carcassonne;

import java.util.ArrayList;

import com.mk.carcassonne.drawables.Brick;
import com.mk.carcassonne.drawables.CommandBar;
import com.mk.carcassonne.drawables.Drawable;

import android.content.Context;
import android.content.Intent;
import android.graphics.Canvas;
import android.graphics.Color;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.widget.ImageView;

public class Panel extends SurfaceView implements SurfaceHolder.Callback{
	private CanvasThread canvasthread;
	private CommandBar _commandBar;
	
	private Position _shift = new Position(0, 0);
	
	public Panel(Context context, AttributeSet attrs) {
		super(context, attrs); 
	
	    getHolder().addCallback(this);
	    canvasthread = new CanvasThread(getHolder(), this);
	    setFocusable(true);
	}

	public Panel(Context context)
	{
		super(context);
		
		getHolder().addCallback(this);
		setFocusable(true);
		
		GlobalData.addBrickPlacement(new Position(0, 0));
    }

	@Override
	public void onDraw(Canvas canvas) {
		canvas.drawColor(Color.BLACK);
		
		for (Drawable d : GlobalData.getPlacedBricks()) {
			d.draw(getContext(), canvas, _shift);
		}
		
		for(Drawable d : GlobalData.getPlacedFollowers())
		{
			d.draw(getContext(), canvas, _shift);
		}
		
		if(_commandBar != null)
		{
			_commandBar.draw(getContext(), canvas, _shift);
		}
	}
	 
	@Override
	public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
	}
	
	@Override
	public void surfaceCreated(SurfaceHolder holder) {
		canvasthread = new CanvasThread(getHolder(), this);
			canvasthread.setRunning(true);
			canvasthread.start();
	}
	
	@Override
	public void surfaceDestroyed(SurfaceHolder holder) 
	{
		boolean retry = true;
		canvasthread.setRunning(false);
		while (retry)
		{
			try {
				canvasthread.join();
				retry = false;
			} catch (InterruptedException e) {
				// we will try it again and again...
			}
		}
	}
	
	private int lastMoveX, lastMoveY, totalDeltaX, totalDeltaY;
	@Override
	public boolean onTouchEvent(MotionEvent event)
	{
		synchronized (canvasthread.getSurfaceHolder()) 
		{
			switch(event.getAction())
			{
				case MotionEvent.ACTION_DOWN:
					totalDeltaX = lastMoveX = (int)event.getX();
					totalDeltaY = lastMoveY = (int)event.getY();
					return true;
				case MotionEvent.ACTION_MOVE:
					
					int deltaX = lastMoveX - (int)event.getX();
					int deltaY = lastMoveY - (int)event.getY();
					
					_shift.setX(_shift.getX() - deltaX);
					_shift.setY(_shift.getY() - deltaY);
					
					lastMoveX = (int)event.getX();
					lastMoveY = (int)event.getY();
					
					return true;
				case MotionEvent.ACTION_UP:
					totalDeltaX -= (int)event.getX();
					totalDeltaY -= (int)event.getY();
					if( Math.abs(totalDeltaX) < 5 && Math.abs(totalDeltaY) < 5)
					{
						if(handleClick(event))
							return true;
					}
					
				default:
					return super.onTouchEvent(event);
			}
		}
	}
	
	private boolean handleClick(MotionEvent event)
	{
		if(!GlobalData.isPlaceFollowerDialogVisible())
		{
			if(isCommandBarClicked(event))
			{
				Position rotateButtonPosition = _commandBar.getRotateButtonPosition();
				if(event.getX() >= rotateButtonPosition.getX() && event.getX() < rotateButtonPosition.getX() + Global.BRICK_SIZE  && event.getY() >= rotateButtonPosition.getY() && event.getY() < rotateButtonPosition.getY() + Global.BRICK_SIZE)
				{
					Brick nextBrick = GlobalData.getNextBrick();
					if(nextBrick != null)
					{
						Global.SoundManager.playSound(R.raw.knock);
						nextBrick.rotate();
					}
				}
				return true;
			}
			
			Brick brick = GlobalData.getNextBrick();
			if(brick != null)
			{
				int x = (int)Math.floor((event.getX() - _shift.getX()) / Global.BRICK_SIZE);
				int y = (int)Math.floor((event.getY() - _shift.getY()) / Global.BRICK_SIZE);
				Position clickedPosition = new Position(x, y);
				
				if(isSpaceAvailable(clickedPosition) && isBrickCompatibleWithNeighbours(clickedPosition))
				{
					Global.SoundManager.playSound(R.raw.plopp);
					
					brick.setPosition(clickedPosition);
					GlobalData.addPlacedBrick(brick);
					
					GlobalData.addBrickPlacement(clickedPosition);
					
					if(brick.getFollowerPlacementCollection().size() > 0 && GlobalData.getRemainingFollowers(1) > 0)
					{
						GlobalData.setPlaceFollowerDialogVisibility(true);
						
						View parent = (View)getParent();
						final View placeFollowerDialog = parent.findViewById(R.id.placeFollowerDialog);
						placeFollowerDialog.setVisibility(View.VISIBLE);
						ImageView placeFollowerButton = (ImageView)placeFollowerDialog.findViewById(R.id.placeFollowerButton);
						placeFollowerButton.setOnClickListener(new OnClickListener() {
							@Override
							public void onClick(View v) {
								placeFollowerDialog.setVisibility(View.INVISIBLE);
								GlobalData.setPlaceFollowerDialogVisibility(false);
								Global.SoundManager.playSound(R.raw.knock);
								Intent myIntent = new Intent(getContext(), PlaceFollowerActivity.class);
								getContext().startActivity(myIntent);
							}
						});
						
						ImageView placeFollowerCancelButton = (ImageView)placeFollowerDialog.findViewById(R.id.placeFollowerCancelButton);
						placeFollowerCancelButton.setOnClickListener(new OnClickListener() {
							@Override
							public void onClick(View v) {
								placeFollowerDialog.setVisibility(View.INVISIBLE);
								GlobalData.setPlaceFollowerDialogVisibility(false);
								Global.SoundManager.playSound(R.raw.drop);
							}
						});
					}
					
					GlobalData.setNextBrick(Global.BrickRepository.getNext());
					_commandBar.setNextBrick(GlobalData.getNextBrick());
					return true;
				}
				else
				{
					Global.SoundManager.playSound(R.raw.drop);
				}
			}
		}
		
		return false;
	}
	
	private boolean isBrickCompatibleWithNeighbours(Position position)
	{
		ArrayList<Position> neigbourPositions = GameLogicUtils.getNeighbourPositions(position);
		ArrayList<Brick> neighbourBricks = GameLogicUtils.getBricksAtPositions(neigbourPositions, GlobalData.getPlacedBricks());
		
		if(neighbourBricks.size() == 0)
			return false;
		
		for(Brick b : neighbourBricks)
		{
			if(!GameLogicUtils.areBricksCompatible(b, GlobalData.getNextBrick(), position))
			{
				return false;
			}
		}
		
		return true;
	}

	private boolean isSpaceAvailable(Position position)
	{
		for (Position p : GlobalData.getBrickPlacements()) {
			if(p.equals(position))
				return false;
		}
		
		return true;
	}
	
	private boolean isCommandBarClicked(MotionEvent event) {
		return event.getY() > (Global.SCREEN_SIZE_Y - Global.COMMAND_BAR_HEIGHT);
	}

	public void setCommandBar(CommandBar commandBar)
	{
		_commandBar = commandBar;
	}

	public void setUpShift()
	{
		
		_shift.setX(Global.SCREEN_SIZE_X / 2 - Global.BRICK_SIZE / 2);
		_shift.setY(Global.SCREEN_SIZE_Y / 2 - Global.BRICK_SIZE / 2 - Global.COMMAND_BAR_HEIGHT / 2);
	}
}   